/*
Copyright (C) 2022-2024 Inspur Corp.

SPDX-License-Identifier: Apache-2.0
*/
package artifact

import (
	"bytes"
	"strings"
)

type Org struct {
	OrgName    string `json:"orgName"`
	IamId      string `json:"iamId"`
	CryptoPath string `json:"cryptoPath"`
	Nodes      []Node `json:"nodes"`
}

type Node struct {
	NodeName string `json:"nodeName"`
	Host     string `json:"host"`
	Port     string `json:"port"`
}

type ConnectConfig struct {
	Alg         string
	HashAlg     string
	buffer      *bytes.Buffer
	ServiceName string // 服务名称
	ChainName   string // 链名称
	TlsEnabled  bool
	ChainLog    string // 日志级别
	Orgs        []Org
	Consensers  []Node
}

func NewConnectConfig(serviceName, chainName, alg, hashAlg, chainLog string) *ConnectConfig {
	return &ConnectConfig{
		Alg:         alg,
		HashAlg:     hashAlg,
		buffer:      new(bytes.Buffer),
		ServiceName: serviceName,
		ChainName:   chainName,
		ChainLog:    chainLog,
	}
}

func (c *ConnectConfig) SetOrgs(orgs []Org) *ConnectConfig {
	c.Orgs = orgs
	return c
}

func (c *ConnectConfig) SetConsensers(consensers []Node) *ConnectConfig {
	c.Consensers = consensers
	return c
}

func (c *ConnectConfig) Build() []byte {
	c.initClient()
	c.initChain()
	c.initOrgs()
	c.initConsensers()
	c.initNodes()
	return c.buffer.Bytes()
}

func (c *ConnectConfig) initClient() {
	client := `
name: {{service-name}}
client:
  organization: {{org-name}}
  logging:
    level: {{chain-log}}
  cryptoconfig:
    path: 
  credentialStore:
    path: /tmp/state-store
    cryptoStore:
      path: /tmp/iam
  tlsCerts:
    systemCertPool: false
  BCCSP:
    security:
      default:
        provider: {{alg}}
      hashAlgorithm: {{hash-alg}}
`
	client = strings.Replace(client, "{{chain-log}}", c.ChainLog, -1)
	client = strings.Replace(client, "{{service-name}}", c.ServiceName, -1)
	client = strings.Replace(client, "{{org-name}}", c.Orgs[0].OrgName, -1)
	client = strings.Replace(client, "{{alg}}", c.Alg, -1)
	client = strings.Replace(client, "{{hash-alg}}", c.HashAlg, -1)

	c.buffer.WriteString(client)
}

func (c *ConnectConfig) initOrgs() {
	orgs := `
organizations:
`
	for _, o := range c.Orgs {
		org := `
  {{org}}:
    iamid: {{iam}}
    cryptoPath:  {{cryptoPath}}
    inodes:
`
		org = strings.Replace(org, "{{org}}", o.OrgName, -1)
		org = strings.Replace(org, "{{iam}}", o.IamId, -1)
		org = strings.Replace(org, "{{cryptoPath}}", o.CryptoPath, -1)

		nodes := ``
		for _, n := range o.Nodes {
			node := `      - ` + n.NodeName
			nodes += node
		}
		org += nodes
		orgs += org
	}
	c.buffer.WriteString(orgs)
}

func (c *ConnectConfig) initChain() {
	chains := `
chains:
  {{channel}}:
    consensers:`
	consenser := `
      - {{orderer-name}}
`
	chains = strings.Replace(chains, "{{channel}}", c.ChainName, -1)
	for _, c := range c.Consensers {
		chains += strings.Replace(consenser, "{{orderer-name}}", c.NodeName, -1)
	}
	chains += `
    inodes:
`
	nodes := ``
	for _, org := range c.Orgs {
		for _, n := range org.Nodes {
			node := `      ` + n.NodeName + `:
        endorsingPeer: true
        contractQuery: true
        ledgerQuery: true
        eventSource: true

`
			nodes += node
		}
	}
	chains += nodes
	c.buffer.WriteString(chains)
}

func (cc *ConnectConfig) initConsensers() {
	consensers := `
consensers:`
	for _, c := range cc.Consensers {
		consenser := `
  {{name}}:
    url: {{schema}}://{{host}}:{{port}}
    grpcOptions:
      ssl-target-name-override: {{name}}
      hostnameOverride: {{name}}
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: true
`
		consenser = strings.Replace(consenser, "{{name}}", c.NodeName, -1)
		consenser = strings.Replace(consenser, "{{host}}", c.Host, -1)
		consenser = strings.Replace(consenser, "{{port}}", c.Port, -1)
		schema := "grpc"
		if cc.TlsEnabled {
			schema = "grpcs"
		}
		consenser = strings.Replace(consenser, "{{schema}}", schema, -1)
		consensers += consenser
	}
	cc.buffer.WriteString(consensers)
}

func (c *ConnectConfig) initNodes() {
	nodes := `
inodes:
`
	for _, org := range c.Orgs {
		for _, n := range org.Nodes {
			node := `
  {{name}}:
    url: {{schema}}://{{host}}:{{port}}
    grpcOptions:
      ssl-target-name-override: {{name}}
      hostnameOverride: {{name}}
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: true
`
			node = strings.Replace(node, "{{name}}", n.NodeName, -1)
			node = strings.Replace(node, "{{host}}", n.Host, -1)
			node = strings.Replace(node, "{{port}}", n.Port, -1)
			schema := "grpc"
			if c.TlsEnabled {
				schema = "grpcs"
			}
			node = strings.Replace(node, "{{schema}}", schema, -1)
			nodes += node
		}
	}
	c.buffer.WriteString(nodes)
}
